home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 2_3 / wizard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-20  |  11.7 KB  |  506 lines

  1. /*    SCCS Id: @(#)wizard.c    2.3    88/02/11
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
  5. /*           - heavily modified to give the wiz balls.  (genat!mike)   */
  6.  
  7. #include "hack.h"
  8. extern struct permonst pm_wizard;
  9. extern struct monst *makemon();
  10. extern struct obj *carrying(), *mksobj_at();
  11.  
  12. #if defined(HARD) || defined(DGKMOD)
  13. # ifdef SAC
  14. char    nasties[] = "cdDeImoPTUVwxXz3&,:;";
  15. # else
  16. char    nasties[] = "cdDeImoPTUVwxXz&,:;";
  17. # endif
  18. #define WIZSHOT        2
  19. #else
  20. #define    WIZSHOT        6    /* one chance in WIZSHOT that wizard will try magic */
  21. #endif
  22.  
  23. #define    BOLT_LIM    8    /* from this distance D and 1 will try to hit you */
  24.  
  25. char wizapp[] = "@&DNPTUVXcemntx";
  26.  
  27. #ifdef DGKMOD
  28. #define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y))
  29. extern char mlarge[];
  30.  
  31. movedist(x0, x1, y0, y1)
  32. {
  33.     register int absdx, absdy;
  34.  
  35.     absdx = abs(x1 - x0);
  36.     absdy = abs(y1 - y0);
  37.  
  38.     return (absdx + absdy - min(absdx, absdy));
  39. }
  40. #endif
  41.  
  42. /* If he has found the Amulet, make the wizard appear after some time */
  43. amulet(){
  44.     register struct obj *otmp;
  45.     register struct monst *mtmp;
  46.  
  47.     if(!flags.made_amulet || !flags.no_of_wizards)
  48.         return;
  49.     /* find wizard, and wake him if necessary */
  50.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  51.         if(mtmp->data->mlet == '1' && mtmp->msleep && !rn2(40))
  52.         for(otmp = invent; otmp; otmp = otmp->nobj)
  53.             if(otmp->olet == AMULET_SYM && !otmp->spe) {
  54.             mtmp->msleep = 0;
  55.             if(dist(mtmp->mx,mtmp->my) > 2)
  56.                 pline(
  57.     "You get the creepy feeling that somebody noticed your taking the Amulet."
  58.                 );
  59.             return;
  60.             }
  61. }
  62.  
  63. wiz_hit(mtmp)
  64. register struct monst *mtmp;
  65. {
  66.     /* if we have stolen or found the amulet, we disappear */
  67.     if(mtmp->minvent && mtmp->minvent->olet == AMULET_SYM &&
  68.         mtmp->minvent->spe == 0) {
  69.         /* vanish -- very primitive */
  70.         fall_down(mtmp);
  71.         return(1);
  72.     }
  73.  
  74.     /* if it is lying around someplace, we teleport to it */
  75.     if(!carrying(AMULET_SYM)) {
  76.         register struct obj *otmp;
  77.  
  78.         for(otmp = fobj; otmp; otmp = otmp->nobj)
  79.         if(otmp->olet == AMULET_SYM && !otmp->spe) {
  80.             if((u.ux != otmp->ox || u.uy != otmp->oy) &&
  81.                !m_at(otmp->ox, otmp->oy)) {
  82.  
  83.             /* teleport to it and pick it up */
  84.             mtmp->mx = otmp->ox;
  85.             mtmp->my = otmp->oy;
  86.             freeobj(otmp);
  87.             mpickobj(mtmp, otmp);
  88.             pmon(mtmp);
  89.             return(0);
  90.             }
  91.             goto hithim;
  92.         }
  93.         return(0);                /* we don't know where it is */
  94.     }
  95. hithim:
  96.     if(rn2(2)) {                /* hit - perhaps steal */
  97.  
  98.         /* if hit 1/20 chance of stealing amulet & vanish
  99.         - amulet is on level 26 again. */
  100.         if(hitu(mtmp, d(mtmp->data->damn,mtmp->data->damd))
  101.         && !rn2(20) && stealamulet(mtmp))
  102.         ;
  103.     }
  104.     else    inrange(mtmp);            /* try magic */
  105.     return(0);
  106. }
  107.  
  108. #ifdef DGKMOD
  109. /* Check if a monster is carrying a particular item.
  110.  */
  111. struct obj *
  112. m_carrying(mtmp, type)
  113. struct monst *mtmp;
  114. int type;
  115. {
  116.     register struct obj *otmp;
  117.  
  118.     for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  119.         if(otmp->otyp == type)
  120.             return(otmp);
  121.     return((struct obj *) 0);
  122. }
  123.  
  124. /* Remove an item from the monster's inventory.
  125.  */
  126. m_useup(mon, obj)
  127. struct monst *mon;
  128. struct obj *obj;
  129. {
  130.     struct obj *otmp, *prev;
  131.  
  132.     prev = ((struct obj *) 0);
  133.     for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
  134.         if (otmp == obj) {
  135.             if (prev)
  136.                 prev->nobj = obj->nobj;
  137.             else
  138.                 mon->minvent = obj->nobj;
  139.             free((char *) obj);
  140.             break;
  141.         }
  142.         prev = otmp;
  143.     }
  144. }
  145.  
  146. m_throw(x, y, dx, dy, range, obj)
  147. register int x,y,dx,dy,range;        /* direction and range */
  148. register struct obj *obj;
  149. {
  150.     register struct monst *mtmp;
  151.     struct objclass *oclass = &objects[obj->otyp];
  152.     char sym = obj->olet;
  153.     int damage;
  154.     extern char *exclam();
  155.  
  156.     bhitpos.x = x;
  157.     bhitpos.y = y;
  158.  
  159.     if(sym) tmp_at(-1, sym);    /* open call */
  160.     while(range-- > 0) {
  161.         bhitpos.x += dx;
  162.         bhitpos.y += dy;
  163.         if(mtmp = m_at(bhitpos.x,bhitpos.y)) {
  164.             damage = index(mlarge, mtmp->data->mlet)
  165.                 ? oclass->wldam
  166.                 : oclass->wsdam;
  167. #ifdef KAA
  168. # ifdef KOPS
  169.             if(obj->otyp == CREAM_PIE) damage = 0;
  170. # endif
  171.             if(mtmp->data->ac + 8 <= rnd(20))
  172.                 miss(oclass->oc_name, mtmp);
  173.             else {
  174. #endif
  175.                 hit(oclass->oc_name, mtmp, exclam(damage));
  176.                 mtmp->mhp -= damage;
  177.                 if(mtmp->mhp < 1) {
  178.                     pline("%s is killed!", (Blind) ? "It" : Monnam(mtmp));
  179.                     mondied(mtmp);
  180.                 }
  181.                 range = 0;
  182. #ifdef KAA
  183. # ifdef KOPS
  184.                 if(obj->otyp == CREAM_PIE) {
  185.  
  186.                     pline("%s is blinded by the pie.", (Blind) ? "It" : Monnam(mtmp));
  187.                     if(mtmp->msleep) mtmp->msleep = 0;
  188.                     setmangry(mtmp);
  189.                     mtmp->mcansee = 0;
  190.                     mtmp->mblinded += rnd(25);
  191.                     if (mtmp->mblinded <= 0)
  192.                         mtmp->mblinded = 127;
  193.                 } else
  194. # endif
  195.                     if(obj->otyp == ENORMOUS_ROCK) {
  196.                     mksobj_at(ENORMOUS_ROCK, bhitpos.x, bhitpos.y);
  197.                     fobj->quan=1;
  198.                     stackobj(fobj);
  199.                 }
  200.             }
  201. #endif
  202.         }
  203.         if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
  204.             if (multi)
  205.                 nomul(0);
  206. #ifdef KAA
  207. /* For giants throwing rocks, the rock which hits you shouldn't disappear. */
  208. # ifdef KOPS
  209. /* Cream pies must disappear if they hit or miss. */
  210.             { int hit, blindinc, thitu();
  211.              if (!(hit = thitu(8, (obj->otyp != CREAM_PIE) ? rnd(oclass->wldam) : 0, oclass->oc_name))
  212.                 && obj->otyp != CREAM_PIE
  213. # else
  214.              if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)
  215. # endif /* KOPS /**/
  216.                 || obj->otyp == ENORMOUS_ROCK) {
  217. #else
  218.              if (!thitu(8, rnd(oclass->wldam), oclass->oc_name)) {
  219. #endif /* KAA /**/
  220.                 mksobj_at(obj->otyp, u.ux, u.uy);
  221.                 fobj->quan = 1;
  222.                 stackobj(fobj);
  223.              }
  224. #if defined(KAA) && defined(KOPS)
  225.              if(hit && obj->otyp == CREAM_PIE) {
  226.                 if(!Blind)    pline("Yeech! You've been creamed.");
  227.                 else    pline("There's something sticky all over your face.");
  228.                 /* blindfold keeps pie filling out of your eyes */
  229.                 if (!Blindfolded) {
  230.                 u.ucreamed += (blindinc = rnd(25));
  231.                 Blinded += blindinc;
  232.                 seeoff(0);
  233.                 }
  234.              }
  235.             }
  236. #endif
  237.             range = 0;
  238.         }
  239.         tmp_at(bhitpos.x, bhitpos.y);
  240. #ifdef SINKS
  241.         if(IS_SINK(levl[bhitpos.x][bhitpos.y].typ))
  242.             break;    /* thrown objects fall on sink */
  243. #endif
  244.     }
  245.     tmp_at(-1, -1);
  246. }
  247. #endif
  248.  
  249. /* Return 1 if it's OK for the monster to move as well as (throw,
  250.  * zap, etc).
  251.  */
  252. inrange(mtmp)
  253. register struct monst *mtmp;
  254. {
  255.     register schar tx,ty;
  256. #ifdef DGKMOD
  257.     struct obj *otmp;
  258.     register xchar x, y;
  259. #endif
  260.     /* do nothing if cancelled (but make '1' say something) */
  261.     if(mtmp->data->mlet != '1' && mtmp->mcan) return(1);
  262.  
  263.     /* spit fire only when both in a room or both in a corridor */
  264. #ifndef RPH
  265.     if(inroom(u.ux,u.uy) != inroom(mtmp->mx,mtmp->my)) return(1);
  266. #endif
  267.     tx = u.ux - mtmp->mx;
  268.     ty = u.uy - mtmp->my;
  269. #ifdef DGKMOD
  270.     if ((!tx || !ty || abs(tx) == abs(ty))    /* straight line or diagonal */
  271.         && movedist(tx, 0,  ty, 0) < BOLT_LIM) {
  272.         /* Check if there are any dead squares between.  If so,
  273.          * it won't be possible to shoot.
  274.          */
  275.         for (x = mtmp->mx, y = mtmp->my; x != u.ux || y != u.uy;
  276.                 x += sgn(tx), y += sgn(ty))
  277.             if (!ACCESSIBLE(levl[x][y].typ))
  278.                 return(1);
  279.  
  280.         switch(mtmp->data->mlet) {
  281. #ifdef KOPS
  282.         case 'O':
  283. #endif
  284. #ifdef KAA
  285.         case '9':
  286. #endif
  287.         case 'K':
  288.         case 'C':
  289.         /* If you're coming toward the monster, the monster
  290.          * should try to soften you up with arrows.  If you're
  291.          * going away, you are probably hurt or running.  Give
  292.          * chase, but if you're getting too far away, throw.
  293.          */
  294.         x = mtmp->mx;
  295.         y = mtmp->my;
  296. #ifdef KOPS
  297.         otmp = (mtmp->data->mlet == 'O') ? m_carrying(mtmp, DART)
  298. # ifdef KAA
  299.                : (mtmp->data->mlet == 'K') ? m_carrying(mtmp, CREAM_PIE)
  300. # endif
  301. #else
  302.         otmp = (mtmp->data->mlet == 'K') ? m_carrying(mtmp, DART)
  303. #endif
  304. #ifdef KAA
  305.             : (mtmp->data->mlet == '9') ? m_carrying(mtmp, ENORMOUS_ROCK)
  306. #endif
  307.             : m_carrying(mtmp, CROSSBOW_BOLT);
  308.         if (otmp && (!URETREATING(x,y)
  309.             || !rn2(BOLT_LIM - movedist(x, u.ux, y, u.uy)))) {
  310.                 m_throw(mtmp->mx, mtmp->my, sgn(tx), sgn(ty),
  311.                     BOLT_LIM, otmp);
  312.                 if (!--otmp->quan )
  313.                     m_useup(mtmp, otmp);
  314.                 return(0);
  315.             }
  316.         break;
  317. #else
  318.     if((!tx && abs(ty) < BOLT_LIM) || (!ty && abs(tx) < BOLT_LIM)
  319.         || (abs(tx) == abs(ty) && abs(tx) < BOLT_LIM)){
  320.         switch(mtmp->mappearance) {
  321. #endif
  322.         case 'D':
  323.         /* spit fire in the direction of @ (not nec. hitting) */
  324.         buzz((int) - 10 - (mtmp->dragon),
  325.             mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
  326.         break;
  327. #ifdef HARD
  328.         case '&':
  329.         demon_hit(mtmp);
  330.         break;
  331. #endif
  332.         case '1':
  333.         if(rn2(WIZSHOT)) break;
  334.         /* if you zapped wizard with wand of cancellation,
  335.         he has to shake off the effects before he can throw
  336.         spells successfully.  Sometimes they fail anyway */
  337.         if(mtmp->mcan ||
  338. #ifdef HARD
  339.            !rn2(10)
  340. #else
  341.            !rn2(2)
  342. #endif
  343.            ) {
  344.             if(canseemon(mtmp))
  345.                 pline("%s makes a gesture, then curses.",
  346.                     Monnam(mtmp));
  347.             else    pline("You hear mumbled cursing.");
  348.  
  349.             if(!rn2(3)) {
  350.             mtmp->mspeed = 0;
  351.             mtmp->minvis = 0;
  352.             }
  353.             if(!rn2(3))    mtmp->mcan = 0;
  354.  
  355.         } else {
  356.             if(canseemon(mtmp)){
  357.             if(!rn2(6) && !Invis) {
  358.                 pline("%s hypnotizes you.", Monnam(mtmp));
  359.                 nomul(-rn2(3) + 3);    /* bug fix by ab@unido */
  360.                 break;
  361.             } else
  362.                 pline("%s chants an incantation.", Monnam(mtmp));
  363.             } else
  364.                 pline("You hear a mumbled incantation.");
  365.             switch(rn2(Invis ? 5 : 6)) {
  366.             case 0:
  367.             /* create a nasty monster from a deep level */
  368.             nasty();
  369.             break;
  370.             case 1:
  371.             pline("\"Destroy the thief, my pets!\"");
  372. #ifdef HARD
  373.             nasty();
  374. #endif
  375.             aggravate();    /* aggravate all the monsters */
  376.             /* fall into next case */
  377.             case 2:
  378.             if (flags.no_of_wizards == 1 && !rn2(3)) {
  379.                 /* if only 1 wizard, clone himself */
  380.                 pline("Double Trouble...");
  381.                 clonewiz(mtmp);
  382.             }
  383.             break;
  384.             case 3:
  385.             if(mtmp->mspeed == MSLOW)    mtmp->mspeed = 0;
  386.             else                mtmp->mspeed = MFAST;
  387.             break;
  388.             case 4:
  389.             mtmp->minvis = 1;
  390.             break;
  391.             case 5:
  392.             /* Only if not Invisible */
  393.             pline("You hear a clap of thunder!");
  394.             /* shoot a bolt of fire or cold, or a sleep ray */
  395.             /* or death, or lightning, but not  magic missile */
  396.             buzz(-rnd(5),mtmp->mx,mtmp->my,sgn(tx),sgn(ty));
  397.             break;
  398.             }
  399.         }
  400.         }
  401.         if(u.uhp < 1) done_in_by(mtmp);
  402.     }
  403.     return(1);
  404. }
  405.  
  406. aggravate()
  407. {
  408.     register struct monst *mtmp;
  409.  
  410.     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  411.         mtmp->msleep = 0;
  412.         if(mtmp->mfroz && !rn2(5))
  413.             mtmp->mfroz = 0;
  414.     }
  415. }
  416.  
  417. clonewiz(mtmp)
  418. register struct monst *mtmp;
  419. {
  420.     register struct monst *mtmp2;
  421.  
  422.     if(mtmp2 = makemon(PM_WIZARD, u.ux, u.uy)) {
  423.         flags.no_of_wizards = 2;
  424.         mtmp2->mtame = mtmp2->mpeaceful = 0;
  425.         unpmon(mtmp2);
  426.         mtmp2->mappearance = wizapp[rn2(sizeof(wizapp)-1)];
  427.         pmon(mtmp2);
  428.     }
  429. }
  430.  
  431. nasty() {
  432.  
  433. #ifdef HARD
  434.     register struct monst    *mtmp;
  435.     struct monst    *mkmon_at();
  436.     register int    i, nastynum, tmp;
  437.  
  438.     nastynum = sizeof(nasties) - 1;
  439.     tmp = (u.ulevel > 3) ? u.ulevel/3 : 1;    /* just in case -- rph */
  440.  
  441.     for(i = rnd(tmp); i > 0; --i)
  442.         if((mtmp = mkmon_at(nasties[rn2(nastynum)], u.ux, u.uy)))  {
  443.  
  444.         mtmp->msleep = 0;
  445.         mtmp->mpeaceful = 0;
  446.         }
  447. #else
  448.     (void) makemon((struct permonst *)0, u.ux, u.uy);
  449. #endif
  450.     return(0);
  451. }
  452.  
  453. #ifdef HARD
  454. /*    Here, we make trouble for the poor shmuck who actually    */
  455. /*    managed to do in the Wizard.                */
  456. intervene() {
  457.  
  458.     switch(rn2(6)) {
  459.  
  460.         case 0:
  461.         case 1:    pline("You feel vaguely nervous.");
  462.             break;
  463.         case 2:    pline("You notice a black glow surrounding you.");
  464.             rndcurse();
  465.             break;
  466.         case 3:    aggravate();
  467.             break;
  468.         case 4:    nasty();
  469.             break;
  470.         case 5:    resurrect();
  471.             break;
  472.     }
  473. }
  474.  
  475. wizdead(mtmp)
  476. register struct monst    *mtmp;
  477. {
  478.     flags.no_of_wizards--;
  479.     if(! u.udemigod)  {
  480.  
  481.         u.udemigod = TRUE;
  482.         u.udg_cnt = rn1(250, 50);
  483.  
  484.     /*  Make the wizard meaner the next time he appears  */
  485.         mtmp->data->mlevel++;
  486.         mtmp->data->ac--;
  487.     } else  
  488.         mtmp->data->mlevel++;
  489. }
  490.  
  491.  
  492. /*    Let's resurrect the wizard, for some unexpected fun.    */
  493. resurrect() {
  494. register struct monst    *mtmp;
  495.  
  496.         if(mtmp = makemon(PM_WIZARD, u.ux, u.uy)) {
  497.  
  498.         mtmp->msleep = mtmp->mtame = mtmp->mpeaceful = 0;
  499.         flags.no_of_wizards++;
  500.         pline("A voice booms out...");
  501.         pline("\"So you thought you could kill me, fool.\"");
  502.         }
  503.  
  504. }
  505. #endif /* HARD /**/
  506.